package com.yh.ldzl.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.BasicService;
import com.ruoyi.system.api.InventoryService;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yh.ldzl.mapper.QcOqcMapper;
import com.yh.ldzl.domain.QcOqc;
import com.yh.ldzl.service.IQcOqcService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 出货检验单Service业务层处理
 * 
 * @author yanghuai
 * @date 2025-07-13
 */
@Service
public class QcOqcServiceImpl implements IQcOqcService 
{
    @Autowired
    private QcOqcMapper qcOqcMapper;
    @Resource
    private InventoryService inventoryService;
    @Resource
    private BasicService basicService;

    /**
     * 自动编码
     */
    private String generateCode(Long type) {
        // 调用远程服务（消费模式，确保每次调用都会递增流水号）
        AjaxResult codeResult = basicService.automaticallyNumbersConsume(type);

        // 确保远程调用返回了结果对象
        if (codeResult == null) {
            throw new ServiceException(String.format("远程获取编码调用失败，返回结果为空，类型: %d", type));
        }

        // 根据该接口的特殊设计，编码直接存放在msg字段
        Object msg = codeResult.get(AjaxResult.MSG_TAG);
        Object code = codeResult.get(AjaxResult.CODE_TAG);
        System.out.println("编码是：" + code);
        // 确保编码内容不为空
        if (msg == null || msg.toString().isEmpty()) {
            throw new ServiceException(String.format("远程获取编码成功，但返回的编码为空，类型: %d, 返回信息: %s", type, msg));
        }

        // 从AjaxResult中正确取出msg部分作为编码
        return msg.toString();
    }

    /**
     * 查询出货检验单
     * 
     * @param oqcId 出货检验单主键
     * @return 出货检验单
     */
    @Override
    public QcOqc selectQcOqcByOqcId(Long oqcId)
    {
        return qcOqcMapper.selectQcOqcByOqcId(oqcId);
    }

    /**
     * 查询出货检验单列表
     * 
     * @param qcOqc 出货检验单
     * @return 出货检验单
     */
    @Override
    public List<QcOqc> selectQcOqcList(QcOqc qcOqc)
    {
        return qcOqcMapper.selectQcOqcList(qcOqc);
    }

    /**
     * 新增出货检验单
     * 
     * @param qcOqc 出货检验单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertQcOqc(QcOqc qcOqc) {
        int success = 0;
        try {
            qcOqc.setCreateBy(SecurityUtils.getUsername());
            TableDataInfo receipt = inventoryService.ckProductSalesLine_qc(qcOqc.getSourceDocId());
            List<?> list = receipt.getRows();
            List<Map<String, Object>> list1 = (List<Map<String, Object>>) list;
            System.out.println("list1 = " + list1);

            int totalRows = 0;
            String oqcCode = null; // 用于统一编码

            for (int i = 0; i < list1.size(); i++) {
                Map<String, Object> map = list1.get(i);

                qcOqc.setCreateBy(qcOqc.getCreateBy());
                qcOqc.setSourceDocId(qcOqc.getSourceDocId());
                qcOqc.setSourceDocType(qcOqc.getSourceDocType());
                qcOqc.setTemplateId(qcOqc.getTemplateId());

                // 只在第一次循环时生成编码
                if (i != 0) {
                    String codeResult = generateCode(11L);
                    qcOqc.setOqcCode(codeResult);
                }


                // 安全赋值
                Object productIdObj = map.get("product_id");
                if (productIdObj != null) {
                    try {
                        qcOqc.setProductId(Long.parseLong(productIdObj.toString()));
                    } catch (NumberFormatException e) {
                        qcOqc.setProductId(null);
                    }
                } else {
                    qcOqc.setProductId(null);
                }

                qcOqc.setProductCode(getNullableString(map, "product_code"));
                qcOqc.setProductName(getNullableString(map, "product_name"));
                qcOqc.setProductSfn(getNullableString(map, "stock_sfn"));
                qcOqc.setUnit(getNullableString(map, "unit"));
                qcOqc.setBatchCode(getNullableString(map, "batch_code"));

                Object salesNumObj = map.get("sales_num");
                if (salesNumObj != null) {
                    try {
                        // 方式1：先转 Double，再转 Long
                        qcOqc.setQuantityOutNum(Double.valueOf(salesNumObj.toString()).longValue());
                    } catch (NumberFormatException e) {
                        qcOqc.setQuantityOutNum(null);   // 给个兜底值
                    }
                } else {
                    qcOqc.setQuantityOutNum(null);
                }

                totalRows += qcOqcMapper.insertQcOqc(qcOqc);
            }

            success = totalRows == list1.size() ? 1 : 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
        return success;
    }
    // 通用取值工具
    private static <T> T getValue(Map<String, Object> map, String key, Class<T> clazz) {
        Object v = map.get(key);
        if (v == null) return null;
        if (clazz == Long.class && v instanceof BigDecimal) {
            return clazz.cast(((BigDecimal) v).longValue());
        }
        if (clazz == BigDecimal.class && v instanceof BigDecimal) {
            return clazz.cast(v);
        }
        return null;
    }

    // 工具方法：安全获取字符串，null 不转 "null"
    private String getNullableString(Map<String, Object> map, String key) {
        Object val = map.get(key);
        return val == null ? null : val.toString();
    }

    /**
     * 修改出货检验单
     * 
     * @param qcOqc 出货检验单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateQcOqc(QcOqc qcOqc)
    {
        qcOqc.setUpdateBy(SecurityUtils.getUsername());

        // 1. 查询 line_id
        Long lineId = qcOqcMapper.selectCkProductSalesLineId(qcOqc.getSourceDocId(),qcOqc.getProductId());
        System.out.println("lineId = " + lineId);
        // 2. 更新检测单
        int row1 = qcOqcMapper.updateQcOqc(qcOqc);
        int row2=0;
        // 3. 更新明细状态
        if (qcOqc.getCheckResult().equals("1")){//检测单合格
            row2 = qcOqcMapper.updateCkProductSalesLineStatus(lineId,"2",qcOqc.getOqcId());
        }else if (qcOqc.getCheckResult().equals("2")){//检测单不合格
            row2 = qcOqcMapper.updateCkProductSalesLineStatus(lineId,"3",qcOqc.getOqcId());
        }
        //判断出货单明细检测情况
        int testResults = qcOqcMapper.selectCkProductSalesTestResults(qcOqc.getSourceDocId());
        if (testResults==1) {//1.全部合格(所有行都已质检且状态为2/合格)
            inventoryService.updateCkProductSalesStatusStatus(qcOqc.getSourceDocId(),"3");
        }else if (testResults==2) {//2.全部不合格(所有行都已质检且状态为3/不合格)
            inventoryService.updateCkProductSalesStatusStatus(qcOqc.getSourceDocId(),"4");
        }else if (testResults==4) {//4.有合格也有不合格(存在合格和不合格的行，且没有未质检的行)
            inventoryService.updateCkProductSalesStatusStatus(qcOqc.getSourceDocId(),"5");
        }

        System.out.println("更新出库表:"+testResults+ "更新出库检测表:"+row1+ "更新出库详情表:"+row2);
        // 4. 必须都大于 0 才算成功
        return (row1 > 0 && row2 > 0) ? 1 : 0;
    }

    /**
     * 批量删除出货检验单
     * 
     * @param oqcIds 需要删除的出货检验单主键
     * @return 结果
     */
    @Override
    public int deleteQcOqcByOqcIds(Long[] oqcIds)
    {
        return qcOqcMapper.deleteQcOqcByOqcIds(oqcIds);
    }

    /**
     * 删除出货检验单信息
     * 
     * @param oqcId 出货检验单主键
     * @return 结果
     */
    @Override
    public int deleteQcOqcByOqcId(Long oqcId)
    {
        return qcOqcMapper.deleteQcOqcByOqcId(oqcId);
    }

    @Override
    public QcOqc selectQcOqcListSourceDocId(Long source_doc_id) {
        return qcOqcMapper.selectQcOqcListSourceDocId(source_doc_id);
    }

    @Override
    public List<Map<String, Object>> selectCkProductSales(String sales_code, String sales_name) {
        return qcOqcMapper.selectCkProductSales( sales_code, sales_name);
    }


}
